/*
 * CSIStyleAggregator.java
 * 
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 * 
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 * 
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */


package vegadataeditor.output.dataAggregators;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import vegadataeditor.VegaStreamContainer;

/**
 * This mimicks the style of aggregation done by Campbell Scientific
 * data loggers. This is important because a lot of legacy data is campbell
 * data logger aggregated measurements.
 *
 * @author lawinslow
 */
public class Downsampler implements ITimeModifier {
    

    /** What length time window is used for the downsample applied.
     * Default is 1 hour. Stored in mills. */
    private long downSpan = 60*60*1000;


    public ModifierResult modify(VegaStreamContainer v) {
        return modify(v,this.createTimes(v.datetime));
    }

    public ModifierResult modify(VegaStreamContainer v, List<Date> newTimes){
        if(newTimes.size()<2){
            throw new IllegalArgumentException("New timestamp list must have" +
                    " at least two timestamps.");
        }
        //TreeMap<Date,Double> outputTS = new TreeMap<Date,Double>();
        ArrayList<Date> outputTimes = new ArrayList<Date>();
        ArrayList<Double> values = new ArrayList<Double>();
        TreeMap<Date,Double> timeseries = new TreeMap<Date,Double>();

        for(int i=0;i<v.datetime.size();i++){
            timeseries.put(v.datetime.get(i), v.values.get(i));
        }
        for(int i=0;i<newTimes.size();i++)
        {
        	//downSamples.put(newTimes.get(i), timeseries.get(newTimes.get(i)));
        	outputTimes.add(newTimes.get(i));
        	values.add(timeseries.get(newTimes.get(i)));
        }
        
        ModifierResult r = new ModifierResult();
        r.setTimes(outputTimes);
        r.setValues(values);
        return r;
    }

    /**
     * Builds a list of new times that the supplied data to which the data
     * will be aggregated. List is in ascending order.
     *
     * @param times Original data timestamps.
     * @return New timestamps to aggregate to.
     */
    private List<Date> createTimes(List<Date> times){
        Date end = (Date)java.util.Collections.max(times);
        Date start = (Date)java.util.Collections.min(times);
        ArrayList<Date> newTimes = new ArrayList<Date>();

        if(start.getTime()%this.downSpan!=0){
            //set start timestamp as the first timestep before
            start = new Date(start.getTime()-start.getTime()%this.downSpan);
        }

        Date tmpDate = start;
        newTimes.add(start);
        while(tmpDate.before(end)){
            tmpDate = new Date(tmpDate.getTime()+this.downSpan);
            newTimes.add(tmpDate);
        }
        
        return newTimes;
    }


    /**
     * Sets downsample timespan in milliseconds. 1 minute would be 60,000
     *
     * @param s Span in milliseconds.
     */
    public void setDownSpan(long s){
        this.downSpan = s;
    }

    /**
     * Returns downsample span in milliseconds.
     *
     * @return Span in milliseconds.
     */
    public long getDownSpan(){
        return this.downSpan;
    }


    public static void main(String[] args)throws java.text.ParseException{
        VegaStreamContainer c = new VegaStreamContainer();

        ArrayList<Date> d = new ArrayList<Date>();
        ArrayList<Double> v = new ArrayList<Double>();
        SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy HH:mm");

        d.add(f.parse("6/27/2009 23:12"));
        v.add(20.5);
        d.add(f.parse("6/28/2009 0:00"));
        v.add(22.45);
        d.add(f.parse("6/28/2009 0:05"));
        v.add(22.475);
        d.add(f.parse("6/28/2009 0:10"));
        v.add(22.35);
        d.add(f.parse("6/28/2009 0:20"));
        v.add(22.4);
        d.add(f.parse("6/28/2009 0:39"));
        v.add(22.1);
        d.add(f.parse("6/28/2009 0:40"));
        v.add(22.2);

        c.datetime = d;
        c.values = v;
        
        Downsampler down = new Downsampler();
        down.setDownSpan(60*60*1000);

        ModifierResult m = down.modify(c);

        System.out.println(m.getTimes());
        System.out.println(m.getValues());







    }
}
